package io.gitee.zhangbinhub.acp.core.file

import io.gitee.zhangbinhub.acp.core.common.CommonTools.doDeleteFile
import io.gitee.zhangbinhub.acp.core.common.CommonTools.getFileExt
import io.gitee.zhangbinhub.acp.core.common.CommonTools.getWebRootAbsPath
import io.gitee.zhangbinhub.acp.core.common.CommonTools.isNullStr
import io.gitee.zhangbinhub.acp.core.common.log.LogFactory.Companion.getInstance
import io.gitee.zhangbinhub.acp.core.file.FileOperation.generateNowTimeString
import io.gitee.zhangbinhub.acp.core.file.pdf.PDFService
import io.gitee.zhangbinhub.acp.core.file.pdf.PageNumberHandle
import io.gitee.zhangbinhub.acp.core.file.pdf.PermissionType
import io.gitee.zhangbinhub.acp.core.file.pdf.fonts.FontLoader
import io.gitee.zhangbinhub.acp.core.file.template.TemplateService
import io.gitee.zhangbinhub.acp.core.file.word.WordType
import java.io.File

object FileTools {
    private val log = getInstance(FileTools::class.java)

    private fun formatFileName(fileName: String): String = if (!isNullStr(fileName)) {
        fileName.replace("/", File.separator).replace("\\", File.separator)
    } else {
        fileName
    }

    private fun generateResultFileName(fileType: FileType, fileName: String): String {
        val name = formatFileName(fileName)
        val nowStr = generateNowTimeString()
        val resultFile: String = if (isNullStr(name)) {
            "${FileOperation.buildTempDir()}${File.separator}$nowStr.${fileType.extName}"
        } else {
            "${File.separator}$name.${fileType.extName}"
        }
        return resultFile
    }

    /**
     * 十六进制字符串转图片文件
     *
     * @param hexString      十六进字符串
     * @param fileName       文件名
     * @param extensionsName 扩展名
     * @param pathFlag       生成图片文件路径标志:0-相对于WebRoot；1-自定义
     * @param resultPathFlag 返回文件路径标志:0-相对于WebRoot；1-绝对路径
     * @param parentPath     生成图片所在目录
     * @param isDelete       是否异步删除临时图片
     * @return 临时图片路径
     */
    @JvmStatic
    @JvmOverloads
    fun hexToImage(
        hexString: String,
        fileName: String,
        extensionsName: String,
        pathFlag: Int,
        resultPathFlag: Int,
        parentPath: String,
        isDelete: Boolean = false
    ): String = FileOperation.hexToImage(
        hexString, fileName, extensionsName, pathFlag, resultPathFlag, parentPath, isDelete
    )

    /**
     * 使用freemarker模板，生成文件
     *
     * @param templateFile 模板路径（绝对路径，或相对于系统模板根路径）
     * @param data         数据
     * @param fileName     目标文件名，带扩展名
     * @return 相对于webRoot路径
     */
    @JvmStatic
    fun exportToFileFromTemplate(templateFile: String, data: Map<String, Any?>?, fileName: String): String = try {
        val name = formatFileName(fileName)
        val nowStr = generateNowTimeString()
        val webRootAdsPath = getWebRootAbsPath()
        val exName = getFileExt(templateFile)
        val resultFile: String = if (isNullStr(name)) {
            FileOperation.buildTempDir() + File.separator + nowStr + exName
        } else {
            FileOperation.buildTempDir() + File.separator + name
        }
        TemplateService.generateFile(formatFileName(templateFile), data, resultFile).replace(webRootAdsPath, "")
            .replace("\\\\".toRegex(), "/")
    } catch (e: Exception) {
        log.error(e.message, e)
        ""
    }

    /**
     * 使用freemarker模板，生成word
     *
     * @param wordType     word类型
     * @param templatePath 模板路径（绝对路径，或相对于webRoot/files/template）
     * @param data         数据
     * @param fileName     目标文件名
     * @return 相对于webRoot路径
     */
    @JvmStatic
    fun exportToWordFromTemplate(
        wordType: WordType, templatePath: String, data: Map<String, Any?>?, fileName: String
    ): String {
        val name = formatFileName(fileName)
        val nowStr = generateNowTimeString()
        val extName: String = if (wordType == WordType.WORD_TYPE_DOCX) {
            ".xml"
        } else {
            ".doc"
        }
        val resultFile: String = if (isNullStr(name)) {
            FileOperation.buildTempDir() + File.separator + nowStr + extName
        } else {
            FileOperation.buildTempDir() + File.separator + name + extName
        }
        return exportToFileFromTemplate(formatFileName(templatePath), data, resultFile)
    }

    /**
     * 通过freemarker模板创建Excel
     *
     * @param fileType     文件类型
     * @param templatePath 模板路径（绝对路径，或相对于webRoot/files/template）
     * @param data         数据
     * @param fileName     生成的文件名
     * @return 相对于webRoot路径
     */
    @JvmStatic
    fun exportToExcelFromTemplate(
        fileType: FileType, templatePath: String, data: Map<String, Any?>?, fileName: String
    ): String =
        exportToFileFromTemplate(formatFileName(templatePath), data, generateResultFileName(fileType, fileName))

    /**
     * HTML页面转为PDF
     *
     * @param htmlStr  html页面源码，必须完整
     * @param fileName 文件名
     * @return 相对于webRoot的文件位置
     */
    @JvmStatic
    @JvmOverloads
    fun htmlToPdf(
        htmlStr: String, fileName: String = "",
        ttcFontPath: String? = null,
        ttcFontIndex: Int = 0
    ): String =
        PDFService().htmlToPdf(htmlStr, generateResultFileName(FileType.PDF, fileName), null, ttcFontPath, ttcFontIndex)
            .replace(getWebRootAbsPath(), "")
            .replace("\\\\".toRegex(), "/")

    /**
     * HTML页面转为PDF
     *
     * @param htmlFilePath html文件路径
     * @param fileName     文件名
     * @param basePath     图片相对路径，为空则默认html文件所在路径
     * @param isDelete     是否删除HTML文件
     * @return 相对于webRoot路径
     */
    @JvmStatic
    @JvmOverloads
    fun htmlFileToPdf(
        htmlFilePath: String, fileName: String, basePath: String? = null, isDelete: Boolean = false,
        ttcFontPath: String? = null,
        ttcFontIndex: Int = 0
    ): String {
        val webRootAdsPath = getWebRootAbsPath()
        val resultFile = generateResultFileName(FileType.PDF, fileName)
        val htmlFile = File(htmlFilePath)
        val foldPath: String
        val base: String
        if (!isNullStr(basePath)) {
            foldPath = formatFileName(basePath!!)
            base = webRootAdsPath
        } else {
            foldPath = htmlFile.getParentFile().getCanonicalPath()
            base = foldPath
        }
        val result = PDFService().htmlFileToPdf(htmlFilePath, resultFile, base, ttcFontPath, ttcFontIndex)
        if (isDelete) {
            doDeleteFile(File(foldPath), false)
            doDeleteFile(htmlFile.getParentFile(), false)
        }
        return result.replace(webRootAdsPath, "").replace("\\\\".toRegex(), "/")
    }

    /**
     * 使用freemarker模板，HTML页面转为PDF
     *
     * @param templatePath 模板路径（绝对路径，或相对于webRoot/files/template）
     * @param data         数据
     * @param fileName     目标文件名称
     * @return 相对于webRoot路径
     */
    @JvmStatic
    @JvmOverloads
    fun htmlToPdfFromTemplate(
        templatePath: String, data: Map<String, Any?>?, fileName: String,
        ttcFontPath: String? = null,
        ttcFontIndex: Int = 0
    ): String =
        PDFService().htmlToPdfForTemplate(
            generateResultFileName(FileType.PDF, fileName),
            formatFileName(templatePath),
            data,
            ttcFontPath,
            ttcFontIndex
        ).replace(getWebRootAbsPath(), "").replace("\\\\".toRegex(), "/")

    /**
     * 图片转PDF
     *
     * @param imageFileNames 图片数组
     * @param resultFileName 目标文件名
     * @param flag           0-自动压缩图片 1-按照宽度压缩图片（所有图片宽度一致）
     * @param isHorizontal   图片是否是横向
     * @param top            上边距（单位磅）
     * @param right          右边距（单位磅）
     * @param bottom         下边距（单位磅）
     * @param left           左边距（单位磅）
     * @return PDF文件绝对路径
     */
    @JvmStatic
    fun imageToPdf(
        imageFileNames: Array<String>,
        resultFileName: String,
        flag: Int,
        isHorizontal: Boolean,
        left: Float,
        right: Float,
        top: Float,
        bottom: Float
    ): String = PDFService().imageToPdf(
        imageFileNames,
        generateResultFileName(FileType.PDF, resultFileName),
        flag,
        isHorizontal,
        left,
        right,
        top,
        bottom
    ).replace(
        getWebRootAbsPath(), ""
    ).replace("\\\\".toRegex(), "/")

    /**
     * PDF增加页码
     *
     * @param pdfFilePath    PDF文件路径，绝对路径或相对路径
     * @param resultFileName 目标文件名称
     * @param isDeleteFile   是否删除源文件
     * @param orientation    0-自动 1-纵向 2-横向
     * @return 相对于webRoot路径
     */
    @JvmStatic
    @JvmOverloads
    fun pdfAddPageNumber(
        pdfFilePath: String, resultFileName: String, isDeleteFile: Boolean, orientation: Int,
        ttcFontPath: String? = null,
        ttcFontIndex: Int = 0
    ): String = PDFService().pdfAddPageEvent(
        pdfFilePath,
        generateResultFileName(FileType.PDF, resultFileName),
        PageNumberHandle(FontLoader.getBaseFont(ttcFontPath, ttcFontIndex)),
        isDeleteFile,
        orientation
    ).replace(
        getWebRootAbsPath(), ""
    ).replace("\\\\".toRegex(), "/")

    /**
     * 给PDF增加水印
     *
     * @param pdfFilePath    pdf源文件
     * @param waterMarkPath  水印图片
     * @param resultFileName 目标文件名
     * @param isDeleteFile   是否删除源文件
     * @return 相对于webRoot路径
     */
    @JvmStatic
    @JvmOverloads
    fun pdfAddWaterMark(
        pdfFilePath: String, waterMarkPath: String, resultFileName: String, isDeleteFile: Boolean = false
    ): String {
        val resultFile = generateResultFileName(FileType.PDF, resultFileName)
        val pdfService = PDFService()
        return pdfService.pdfAddWaterMark(pdfFilePath, waterMarkPath, resultFile, isDeleteFile).replace(
            getWebRootAbsPath(), ""
        ).replace("\\\\".toRegex(), "/")
    }

    /**
     * PDF加密
     *
     * @param pdfFilePath    PDF源文件路径
     * @param resultFileName 目标文件名称
     * @param isDeleteFile   是否删除源文件
     * @return 相对于webRoot路径
     */
    @JvmStatic
    @JvmOverloads
    fun pdfEncrypt(pdfFilePath: String, resultFileName: String, isDeleteFile: Boolean = false): String =
        PDFService().pdfEncrypt(
            pdfFilePath,
            "",
            generateResultFileName(FileType.PDF, resultFileName),
            true,
            null,
            PDFService.PDF_OWNER_PASSWORD,
            PermissionType.ALLOW_COPY.value or PermissionType.ALLOW_PRINTING.value,
            isDeleteFile
        ).replace(
            getWebRootAbsPath(), ""
        ).replace("\\\\".toRegex(), "/")

    /**
     * 合并多个PDF为一个
     *
     * @param fileNames      源文件，绝对路径或相对路径
     * @param resultFileName 目标文件名称
     * @param isDeleteFile   是否删除源文件
     * @return 相对于webRoot路径
     */
    @JvmStatic
    @JvmOverloads
    fun pdfToMerge(fileNames: Array<String>, resultFileName: String, isDeleteFile: Boolean = false): String =
        PDFService().pdfToMerge(fileNames, generateResultFileName(FileType.PDF, resultFileName), isDeleteFile)
            .replace(getWebRootAbsPath(), "").replace("\\\\".toRegex(), "/")
}
